// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package roadmap_dao

import (
	"context"

	"gitcode.com/lvupclub/lvup-api/dao/common"
	"gitcode.com/lvupclub/proto-gen-go.git/src/roadmap_qa_api"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

type BasicThreadInfoDbItem struct {
	Name string `bson:"name"`
}

type ThreadInfoDbItem struct {
	ThreadId          string                      `bson:"_id"`
	RoadmapId         string                      `bson:"roadmapId"`
	BasicInfo         BasicThreadInfoDbItem       `bson:"basicInfo"`
	ThreadState       roadmap_qa_api.THREAD_STATE `bson:"threadState"`
	HasAnswerViewTime bool                        `bson:"hasAnswerViewTime"`
	AnswerViewTime    int64                       `bson:"answerViewTime"`
	AskUserId         string                      `bson:"askUserId"`
	AskViewTime       int64                       `bson:"askViewTime"`
	CreateTime        int64                       `bson:"createTime"`
	UpdateTime        int64                       `bson:"updateTime"` //只有内容变更才会更新
}

func (item *ThreadInfoDbItem) ToThreadInfo() *roadmap_qa_api.ThreadInfo {
	return &roadmap_qa_api.ThreadInfo{
		ThreadId: item.ThreadId,
		BasicInfo: &roadmap_qa_api.BasicThreadInfo{
			Name: item.BasicInfo.Name,
		},
		ThreadState:       item.ThreadState,
		HasAnswerViewTime: item.HasAnswerViewTime,
		AnswerViewTime:    item.AnswerViewTime,
		AskUserId:         item.AskUserId,
		AskViewTime:       item.AskViewTime,
		CreateTime:        item.CreateTime,
		UpdateTime:        item.UpdateTime,
	}
}

type ListThreadParams struct {
	RoadmapId        string
	FiterByAskUserId bool
	AskUserId        string
	FilterByNew      bool
}

func (p *ListThreadParams) genQuery() bson.M {
	queryList := []bson.M{{"roadmapId": p.RoadmapId}}
	if p.FiterByAskUserId {
		queryList = append(queryList, bson.M{"askUserId": p.AskUserId})
	}
	if p.FilterByNew {
		if p.FiterByAskUserId {
			queryList = append(queryList, bson.M{"$expr": bson.M{"$lt": []string{"$askViewTime", "$updateTime"}}})
		} else {
			queryList = append(queryList, bson.M{"$expr": bson.M{"$lt": []string{"$answerViewTime", "$updateTime"}}})
		}
	}
	return bson.M{"$and": queryList}
}

type _ThreadInfoDao struct {
	mc *mongo.Collection
}

func newThreadInfoDao(db *mongo.Database) (*_ThreadInfoDao, error) {
	mc := db.Collection(common.DB_NS_ROADMAP + "qa_thread")
	_, err := mc.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
		{
			Keys: bson.D{{"roadmapId", 1}, {"askUserId", 1}, {"updateTime", 1}},
		},
		{
			Keys: bson.D{{"roadmapId", 1}, {"updateTime", 1}},
		},
	})
	if err != nil {
		return nil, err
	}
	return &_ThreadInfoDao{mc: mc}, nil
}

func (db *_ThreadInfoDao) Insert(ctx context.Context, dbItem *ThreadInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_ThreadInfoDao) Exist(ctx context.Context, roadmapId, threadId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId})
	return count > 0, err
}

func (db *_ThreadInfoDao) Get(ctx context.Context, roadmapId, threadId string) (*ThreadInfoDbItem, error) {
	retItem := &ThreadInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId}).Decode(retItem)
	return retItem, err
}

func (db *_ThreadInfoDao) Remove(ctx context.Context, roadmapId, threadId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId})
	return err
}

func (db *_ThreadInfoDao) RemoveByRoadmap(ctx context.Context, roadmapId string) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{"roadmapId": roadmapId})
	return err
}

func (db *_ThreadInfoDao) Count(ctx context.Context, param *ListThreadParams) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, param.genQuery())
	return uint32(count), err
}

func (db *_ThreadInfoDao) List(ctx context.Context, param *ListThreadParams, offset, limit int64) ([]*ThreadInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, param.genQuery(), options.Find().SetSkip(offset).SetLimit(limit).SetSort(bson.M{"updateTime": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*ThreadInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_ThreadInfoDao) UpdateBasic(ctx context.Context, roadmapId, threadId string, basicItem *BasicThreadInfoDbItem) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId},
		bson.M{"$set": bson.M{
			"basicInfo": basicItem,
		}})
	return err
}

func (db *_ThreadInfoDao) UpdateState(ctx context.Context, roadmapId, threadId string, threadState roadmap_qa_api.THREAD_STATE) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId},
		bson.M{"$set": bson.M{
			"threadState": threadState,
		}})
	return err
}

func (db *_ThreadInfoDao) UpdateAnswerViewTime(ctx context.Context, roadmapId, threadId string, viewTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId},
		bson.M{"$set": bson.M{
			"hasAnswerViewTime": true,
			"answerViewTime":    viewTime,
		}})
	return err
}

func (db *_ThreadInfoDao) UpdateAskViewTime(ctx context.Context, roadmapId, threadId string, viewTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId},
		bson.M{"$set": bson.M{
			"askViewTime": viewTime,
		}})
	return err
}

func (db *_ThreadInfoDao) UpdateUpdateTime(ctx context.Context, roadmapId, threadId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"roadmapId": roadmapId, "_id": threadId},
		bson.M{"$set": bson.M{
			"updateTime": updateTime,
		}})
	return err
}
